home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-01 / gospeed.zip / SPEED.ASM < prev    next >
Assembly Source File  |  1990-05-28  |  11KB  |  327 lines

  1.     page    58,132
  2.     TITLE    Go -- Control (and measure) speed for Heath/Zenith PC
  3.  
  4. ;    (c) Copyright 1987 David E. Tweten
  5.  
  6. ;    All rights reserved.  Permission for distribution is granted
  7. ;    provided that no direct commercial advantage is gained, and
  8. ;    provided that this copyright notice appears on all copies.
  9.  
  10. ;    --------------------------------------------------------------------
  11. ;
  12. ;    Go serves three purposes relating to Dante Bencivengo's "TurboPlus
  13. ;    V2.0" modification to 4.77 MHz Heath/Zenith PCs.  It permits FORMAT
  14. ;    and VERIFY ON to work.  It also permits the user to speed or slow
  15. ;    the processor.  Finally, it measures the processor's speed setting
  16. ;    (primarily for batch file use).  "TurboPlus", the predecessor
  17. ;    version of "TurboPlus V2.0", was described in the June, 1986 issue
  18. ;    of REMark, the journal of the Heath/Zenith Users' Group. 
  19. ;
  20. ;    Due to a quirk in the diskette BIOS, errors will occur when a track
  21. ;    format or verify operation is requested at any high speed, or when
  22. ;    any diskette operation is attempted at 8 MHz.  The terminate-and-
  23. ;    stay-resident portion of this code will prevent the errors from
  24. ;    occuring by slowing the processor for the duration of the
  25. ;    operation, unless it is already operating at the slow (4.77 MHz)
  26. ;    speed.
  27. ;
  28. ;    The optional switch for Go can specify the speed to use when not
  29. ;    formatting or verifying a floppy disk.  It can be "f", which will
  30. ;    set the clock speed to fast, or it can be "s", which will set the
  31. ;    clock speed to slow.  In any but its initial (TSR installing) call,
  32. ;    if no switch is given, Go does not change the speed setting.  On
  33. ;    the initial call, if no argument is given, Go assumes "f".  Go uses
  34. ;    whatever switch character is current.
  35. ;
  36. ;    The termination code for Go is set according to the processor speed
  37. ;    at call, and by whether or not it has previously been called.  The
  38. ;    meaning of its termination code is as follows:
  39. ;
  40. ;         0 - Go has been called before so the TSR portion is already
  41. ;             resident.  Before the call the clock was set to run at
  42. ;             4.77 MHz.
  43. ;
  44. ;         1 - Go has been called before so the TSR portion is already
  45. ;             resident.  Before the call the clock was set to run at
  46. ;             its fast speed.
  47. ;
  48. ;         2 - Go has not been called before.  This call installed the TSR
  49. ;             code and set the clock speed to the specified value (either
  50. ;             Fast or Slow).  If no speed was specified on the call, the
  51. ;             default of Fast was used.
  52. ;
  53. ;         3 - Go has been called in error.  It did nothing.
  54. ;
  55. ;    NOTE that the actual processor speed is the slower of the speed
  56. ;    specified and detected by Go, and the speed specified by the
  57. ;    hardware switch included in the "TurboPlus V2.0".  The actual speed
  58. ;    is indicated by the LED included with the "TurboPlus V2.0" package. 
  59. ;
  60. ;    Written by:  David E. Tweten   <tweten@prandtl.nas.nasa.gov>
  61. ;
  62. ;                                   12141 Atrium Drive
  63. ;                                   Saratoga, CA  95070
  64. ;
  65. ;                                   (408) 446-4131
  66. ;
  67. ;    Inspiration: FV.COM, a program of unstated authorship, included on
  68. ;                 the "TurboPlus" software disk.
  69. ;
  70. ;    Modification History:
  71. ;
  72. ;       1.0      5-10-87  Initial version.
  73. ;
  74. ;    --------------------------------------------------------------------
  75.  
  76. IGROUP    group    _TEXT
  77.  
  78. BLK_HDR_SEGMENT segment at 00000H
  79. blk_flag db    ?            ; 'M' for normal, 'Z' for final block
  80. blk_owner dw    ?            ; segment of owner's PSP
  81. blk_psize dw    ?            ; block size in paragraphs
  82. BLK_HDR_SEGMENT ends
  83.  
  84. STDOUT    equ    1            ; File handle for Standard Output
  85. STDERR    equ    2            ; File handle for Standard Error
  86. CR    equ    0DH            ; ASCII code for Carriage Return
  87. LF    equ    0AH            ; ASCII code for Line Feed
  88. HT    equ    09H            ; ASCII code for Horizontal Tab
  89. LEDS    equ    0C0H            ; Port address of "CPU LEDs"
  90. SLOW    equ    1FH            ; Turn off all LEDs but "RDY"
  91. FAST    equ    3FH            ; Turn off all LEDs
  92. VERIFY    equ    4            ; Diskette sector verify service number
  93. FORMAT    equ    5            ; Format diskette track service number
  94.  
  95.     SUBTTL    Resident Interrupt Filter
  96.     page
  97. _TEXT    segment    para public 'CODE'
  98.     assume    cs:_TEXT,ds:NOTHING,es:NOTHING,ss:NOTHING
  99.  
  100.     org    02CH
  101. env_seg    dw    ?            ; Seg addr for our copy of environment
  102.  
  103.     org    05CH
  104. beg_ovr:                 ; Beginning of overwritten PSP area
  105.  
  106.     org    080H
  107. istrlen    db    ?            ; Invocation string and length
  108. istring    equ    $
  109.  
  110.     org    100h
  111. START:    jmp    go            ; Jump around the resident portion.
  112.  
  113.     org    10CH            ; Offset in paragraph same as beg_ovr
  114. beg_pr:                    ; Beginning of part to move into PSP
  115.  
  116. res_offs equ    (beg_pr-beg_ovr) SHR 4    ; Paragraphs to move resident
  117.  
  118. rom_dsk dd    ?            ; ROM INT 13 service routine address
  119. speed    db    FAST            ; "Normal" speed, set by command switch
  120.  
  121. int_13    proc    far
  122.     pushf                ; IF and TF were cleared by the INT 13.
  123.     cmp    dl,80h            ; If it's a Winchester operation,
  124.     jae    short call_rom        ;  just go do it.
  125. ;
  126. ; The following code block is for TurboPlus V2.0 installations running at
  127. ; speeds below 8.0 MHz.  At 8.0 MHz, all floppy disk operations must be
  128. ; performed at low speed.  Below 8.0 MHz, only "verify sector" and "format
  129. ; track" need to be run at low speed.
  130. ;
  131.     ifndef    MHZ8
  132.     cmp    ah,VERIFY        ; If it's not a verify operation,
  133.     je    short go_slow
  134.     cmp    ah,FORMAT        ;  and it's not a format operation,
  135.     jne    short call_rom        ;  just do it.
  136. go_slow:
  137.     endif
  138. ;
  139. ; The previous code block is for TurboPlus V2.0 installations running at
  140. ; speeds below 8.0 MHz.
  141. ;
  142.     popf                ; Recover flags at entry, and leave
  143.     pushf                ;  them at stack top for simulated INT.
  144.     push    ax
  145.     mov    al,SLOW
  146.     out    LEDS,al            ; Slow to 4.77 MHz.
  147.     pop    ax
  148.     call    rom_dsk            ; Simulate INT 13 with return here.
  149.     push    ax
  150.     mov    al,speed
  151.     out    LEDS,al            ; Resume speed(ing).
  152.     pushf                ; Put flags where we can get them.
  153.     push    bp
  154.     mov    bp,sp
  155.     mov    ax,[bp+10]        ; Extract IF and TF from user's flags,
  156.     and    ax,300H
  157.     or    ax,[bp+2]        ;  merge them with returned flags,
  158.     mov    [bp+10],ax        ;  and put them back for the IRET.
  159.     pop    bp            ; Restore the registers,
  160.     add    sp,+2            ;  ignoring the flags.
  161.     pop    ax
  162.     iret                ; Return to caller with proper flags.
  163.  
  164. call_rom:
  165.     popf                ; Recover flags at entry.
  166.     jmp    rom_dsk            ; Simulate interrupt entry into ROM.
  167. int_13    endp
  168.  
  169. res_bl    equ    $-beg_pr        ; Length of resident
  170. cod_bl    equ    $-int_13        ; Length of resident code
  171.  
  172.     SUBTTL    Non-resident Code
  173.      page
  174.     assume    ds:_TEXT,es:_TEXT,ss:_TEXT
  175. ;
  176. ; Non-resident data
  177. ;
  178. copyright db    "(c) Copyright 1987 David E. Tweten.  All rights reserved."
  179. version    db    "Go version 1.0 installed, for use "
  180.     ifdef    MHZ8
  181.     db    "at"
  182.     else
  183.     db    "below"
  184.     endif
  185.     db    " 8.0 MHz.", CR, LF
  186. VERSION_L equ    $-version
  187. mes_env    db    "Warning: can't return environment copy memory.", CR, LF
  188. MES_ENV_L equ    $-mes_env
  189. mes_err    db    "Error: switch value unrecognized.", CR, LF
  190. MES_ERR_L equ    $-mes_err
  191. mes_use    db    "Usage: go [ "
  192. swchar    db    "*"
  193.     db    "fs ]", CR, LF
  194. MES_USE_L equ    $-mes_use
  195.  
  196.     even
  197.  
  198. sibling    dw    ?            ; Effective PSP segment addr of twin
  199.  
  200. go:
  201.     cld
  202.     mov    ax,3700H        ; Get switch character
  203.     int    21H            ;  (UNDOCUMENTED MS-DOS FUNCTION).
  204.     mov    swchar,dl
  205.     mov    ah,52H            ; Get seg. addr. of first memory block
  206.     int    21H            ;  (UNDOCUMENTED MS-DOS FUNCTION).
  207.     mov    dx,es:[bx-2]
  208.     mov    sibling,ds        ; Initialize PSP seg. addr. to our own.
  209. blkscn:
  210.     assume    es:BLK_HDR_SEGMENT    ; See if we're already installed.
  211.     mov    es,dx
  212.     cmp    blk_flag,'Z'        ; If we've checked the last block,
  213.     je    short first        ;  end this nonsense.
  214.     inc    dx            ; Compute segment address of next
  215.     add    dx,blk_psize        ;  block.
  216.     mov    ax,blk_owner        ; Get block owner's PSP segment addr.
  217.     sub    ax,res_offs        ; Modify it to account for our resident
  218.     mov    es,ax            ;  code shift.
  219.     mov    si,offset int_13    ; Get offset for the resident code.
  220.     mov    di,si
  221.     mov    cx,cod_bl        ; Get resident code byte count.
  222.     repe    cmpsb            ; OK, we've seen the enemy; is he us?
  223.     jne    blkscn            ; If he ain't, keep looking.
  224.     mov    sibling,es        ; Save segment address of our twin.
  225.     mov    ah,es:speed        ; Set our default to our twin's.
  226. first:
  227.     assume    es:_TEXT
  228.     mov    dx,ds
  229.     mov    es,dx
  230.     mov    si,offset istring    ; Initialize argument string pointer
  231.     mov    cl,istrlen        ;  and count.
  232.     xor    ch,ch
  233. whitesp:
  234.     jcxz    short default        ; Skip over leading white space in
  235.     lodsb                ;  argument string.
  236.     dec    cx
  237.     cmp    al,' '
  238.     je    whitesp
  239.     cmp    al,HT
  240.     je    whitesp
  241.     cmp    al,swchar        ; If first non-blank is not the switch
  242.     jne    short badarg        ;  character, return error.
  243.     mov    al,[si]            ; Get the switch value.
  244.     or    al,20H            ; Force it to lowercase.
  245.     mov    ah,FAST            ; If the switch is "/f", it's fast.
  246.     cmp    al,'f'
  247.     je    short found
  248.     mov    ah,SLOW            ; If the switch is "/s", it's slow.
  249.     cmp    al,'s'
  250.     je    short found
  251. badarg:
  252.     mov    ah,40H            ; If none of the above, it's an error;
  253.     mov    dx,offset mes_err    ;  complain bitterly.
  254.     mov    cx,MES_ERR_L
  255.     mov    bx,STDERR
  256.     int    21H
  257. error:
  258.     mov    ah,40H            ; Display usage message.
  259.     mov    dx,offset mes_use
  260.     mov    cx,MES_USE_L
  261.     mov    bx,STDERR
  262.     int    21H
  263.     mov    al,3            ; Set return error status.
  264. exit:
  265.     mov    ah,4ch            ; Exit with status.
  266.     int    21H
  267.  
  268. found:
  269.     mov    al,ah            ; Change to the new speed.
  270.     out    LEDS,al
  271.     mov    es,sibling        ; Note the new default speed.
  272.     xchg    es:speed,ah
  273.     mov    dx,ds
  274.     mov    es,dx
  275. default:
  276.     cmp    dx,sibling
  277.     je    short grabint
  278.     mov    al,0
  279.     cmp    ah,SLOW
  280.     je    exit
  281.     mov    al,1
  282.     jmp    exit
  283.  
  284. grabint:
  285.     mov    ax,3513H        ; Get address of diskette (13H)
  286.     int    21H            ;  interrupt response routine.
  287.     mov    (word ptr rom_dsk)[word * 0],bx ; Move ES:BX to rom_dsk.
  288.     mov    (word ptr rom_dsk)[word * 1],es
  289.     mov    ax,cs            ; Relocate our resident portion.
  290.     mov    es,ax
  291.     mov    si,offset beg_pr
  292.     mov    di,offset beg_ovr
  293.     mov    cx,res_bl
  294.     rep    movsb
  295.     mov    ax,cs            ; Now set new value in the interrupt
  296.     sub    ax,res_offs        ;  vector for 13H
  297.     mov    ds,ax
  298.     mov    dx,offset int_13
  299.     mov    ax,2513H        ;  as int_13.
  300.     int    21H
  301.     mov    ax,cs            ; Restore data segment register.
  302.     mov    ds,ax
  303.     mov    ah,40H
  304.     mov    dx,offset version
  305.     mov    cx,VERSION_L
  306.     mov    bx,STDOUT
  307.     int    21H            ; Display the version number.
  308.     mov    es,env_seg        ; Return space for copy of environment.
  309.     mov    ah,49H
  310.     int    21H
  311.     jnc    short tsr        ; If we can't give back the environment
  312.     mov    ah,40H            ;  copy, complain (but not bitterly).
  313.     mov    dx,offset mes_env
  314.     mov    cx,MES_ENV_L
  315.     mov    bx,STDERR
  316.     int    21H
  317. tsr:
  318.     mov    dx,di            ; Terminate and stay resident.
  319.     add    dx,15
  320.     mov    cl,4
  321.     shr    dx,cl
  322.     mov    ax,3102H        ; Compute size of resident portion in
  323.     int    21H            ;  paragraphs, and leave it behind.
  324.  
  325. _TEXT    ends
  326.     end    START
  327.